﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using HtmlAgilityPack;
using SelfMadeMillionaire.Core.Entities;
using SelfMadeMillionaire.Core.Services;
using YahooFinanceWatcher.Models;

namespace YahooFinanceWatcher.Controllers
{
    public class HomeController : Controller
    {
        private readonly IPortfolioService _portfolioService;
        private readonly ISymbolService _symbolService;

        public HomeController(IPortfolioService portfolioService, ISymbolService symbolService)
		{
            _portfolioService = portfolioService;
            _symbolService = symbolService;
		}

        public ActionResult Index(int? ID)
        {
            HomeModel model = new HomeModel();
            model.Portfolios = _portfolioService.GetAll().OrderBy(x => x.PortfolioName).ToList();

            bool isFound;
            if (ID.HasValue)
            {
                Portfolio selected = _portfolioService.Get(ID.Value);

                model.SelectedId = ID.Value;
                model.SelectedName = selected.PortfolioName;

                List<Symbol> items = selected.Symbols.OrderBy(x => x.SymbolCode).ToList();
                foreach (Symbol item in items)
                    model.InfoList.Add(ParseCompany(model.SelectedId, item.SymbolCode, out isFound));

                InfoList.Clear();
            }
            else
            {
                model.SelectedId = -1;
                model.SelectedName = "New portfolio";
                foreach (CompanyInfo item in InfoList)
                    model.InfoList.Add(ParseCompany(model.SelectedId, item.Symbol, out isFound));
            }

            if (TempData["NotFoundSymbol"] != null)
                if (Convert.ToBoolean(TempData["NotFoundSymbol"]))
                {
                    model.NotFoundSymbol = true;
                }
                        
            return View(model);
        }

        public ActionResult GetSymbols(int id)
        {
            List<CompanyInfo> model = new List<CompanyInfo>();

            bool isFound;
            if (id > 0)
            {
                Portfolio selected = _portfolioService.Get(id);

                List<Symbol> items = selected.Symbols.OrderBy(x => x.SymbolCode).ToList();
                foreach (Symbol item in items)
                    model.Add(ParseCompany(id, item.SymbolCode, out isFound));
            }
            else
            {
                foreach (CompanyInfo item in InfoList)
                    model.Add(ParseCompany(id, item.Symbol, out isFound));
            }

            return PartialView("CompanyInfoList", model);
        }

        [HttpPost]
        public ActionResult GetData(HomeModel model)
        {
            if (ModelState.IsValid)
            {
                bool isFound;
                ParseCompany(model.SelectedId, model.NameCompany, out isFound);

                if (!isFound)
                {
                    TempData["NotFoundSymbol"] = true;
                }
                
                if (model.SelectedId > 0)
                {
                    if (isFound)
                    {
                        Portfolio dbItem = _portfolioService.Get(model.SelectedId);
                        if (!dbItem.Symbols.Any(x => x.SymbolCode.ToLower() == model.NameCompany.ToLower()))
                        {
                            Symbol dbItemSub = new Symbol();
                            dbItemSub.SymbolCode = model.NameCompany;
                            dbItemSub.Status = 1;
                            dbItem.Symbols.Add(dbItemSub);

                            _portfolioService.Update(dbItem);
                        }
                    }

                    return RedirectToAction("Index", new { ID = model.SelectedId });

                }
                else
                {
                    if (isFound)
                    {
                        CompanyInfo ci = new CompanyInfo();
                        ci.Symbol = model.NameCompany;
                        if (!InfoList.Any(x => x.Symbol.ToLower() == model.NameCompany.ToLower()))
                            InfoList.Add(ci);
                    }

                    return RedirectToAction("Index");
                }
                
            }

            return View("Index", model);
        }

        public ActionResult PortfolioDialog(int id)
        {
            PortfolioDialogModel model = new PortfolioDialogModel();
            model.Id = id;
            if (id > 0)
                model.Name = _portfolioService.Get(id).PortfolioName;

            return PartialView("PortfolioDialog", model);
        }

        [HttpPost]
        public ActionResult PortfolioDialog(PortfolioDialogModel model)
        {
            if (ModelState.IsValid)
            {
                if (_portfolioService.GetAll().Any(x => x.PortfolioName.ToLower() == model.Name.ToLower()))
                    ModelState.AddModelError("Name", "Name already exists");
                else
                {
                    bool isNew = (model.Id <= 0);
                    Portfolio dbItem;
                    if (isNew)
                    {
                        dbItem = new Portfolio();
                        dbItem.Symbols = new List<Symbol>();
                    }
                    else
                        dbItem = _portfolioService.Get(model.Id);

                    dbItem.PortfolioName = model.Name;
                    if (isNew)
                    {
                        foreach (CompanyInfo item in InfoList)
                        {
                            Symbol dbItemSub = new Symbol();
                            dbItemSub.SymbolCode = item.Symbol;
                            dbItemSub.Status = 1;
                            dbItem.Symbols.Add(dbItemSub);
                        }
                    }
                                        
                    if (isNew)
                        _portfolioService.Add(dbItem);
                    else
                        _portfolioService.Update(dbItem);

                    return Json(new { success = true, id = dbItem.ID }, JsonRequestBehavior.AllowGet);
                }
            }

            return PartialView(model);
        }

        [HttpPost]
        public ActionResult DeletePortfolio(int id)
        {
            Portfolio dbItem = _portfolioService.Get(id);
            if (dbItem != null)
            {
                dbItem.Symbols.ToList().ForEach(x => _symbolService.Remove(x.ID));
                _portfolioService.Remove(id);
            }

            return RedirectToAction("Index");
        }

        [HttpPost]
        public ActionResult DeleteSymbol(int portfolioId, string symbol)
        {
            if (portfolioId > 0)
            {
                Symbol dbItem = _symbolService.GetAll().Where(x => x.Portfolio.ID == portfolioId && x.SymbolCode == symbol).FirstOrDefault();
                if (dbItem != null)
                    _symbolService.Remove(dbItem.ID);

                return RedirectToAction("Index", new { ID = portfolioId });
            }
            else
            {
                CompanyInfo ci = InfoList.Where(x => x.Symbol == symbol).FirstOrDefault();
                if (ci != null)
                    InfoList.Remove(ci);

                return RedirectToAction("Index");
            }

        }

        public List<CompanyInfo> InfoList
        {
            get
            {
                if (Session["InfoList"] == null)
                {
                    Session["InfoList"] = new List<CompanyInfo>();
                }

                return (List<CompanyInfo>)Session["InfoList"];
            }
        }
        
        [NonAction]
        private CompanyInfo ParseCompany(int portfolioId, string companyName, out bool isFound)
        {
            isFound = false;
            string url = string.Format("http://finance.yahoo.com/q?s={0}", companyName);

            HtmlWeb web = new HtmlWeb();
            HtmlDocument doc = web.Load(url);

            CompanyInfo info = new CompanyInfo();
            info.Symbol = companyName;
            info.Url = url;
            info.PortfolioId = portfolioId;

            var infoNodes = doc.DocumentNode.SelectNodes("//div[@id='yfi_quote_summary_data']");
            if (infoNodes != null)
            {
                foreach (HtmlNode container in infoNodes)
                {
                    isFound = true;
                    /*bool isAdd = false;
                    CompanyInfo info = InfoList.FirstOrDefault(x => x.Symbol == companyName);
                    if (info == null)
                    {
                        info = new CompanyInfo();
                        isAdd = true;
                    }*/

                    HtmlNodeCollection tables = container.SelectNodes("table");
                    for (int j = 0; j < tables.Count; ++j)
                    {
                        HtmlNode table = tables[j];

                        if ((table.Id != "table1") && (table.Id != "table2"))
                            continue;

                        HtmlNodeCollection rows = table.SelectNodes("tr");
                        for (int i = 0; i < rows.Count; ++i)
                        {
                            HtmlNode row = rows[i];

                            HtmlNodeCollection cellsHeader = row.SelectNodes("th");
                            HtmlNodeCollection cellsData = row.SelectNodes("td");

                            string header = cellsHeader[0].InnerText;
                            if (header == "Prev Close:")
                                info.PrevClose = cellsData[0].InnerText;
                            else if (header == "Open:")
                                info.Open = cellsData[0].InnerText;
                            else if (header == "Bid:")
                                info.Bid = cellsData[0].InnerText;
                            else if (header == "Ask:")
                                info.Ask = cellsData[0].InnerText;
                            else if (header == "1y Target Est:")
                                info.TargetEst = cellsData[0].InnerText;
                            else if (header == "Beta:")
                                info.Beta = cellsData[0].InnerText;
                            else if (header == "Next Earnings Date:")
                                info.NextEarningsDate = cellsData[0].InnerText;

                            else if (header == "Day's Range:")
                                info.DaysRange = cellsData[0].InnerText;
                            else if (header == "52wk Range:")
                                info.Wk52Range = cellsData[0].InnerText;
                            else if (header == "Volume:")
                                info.Volume = cellsData[0].InnerText;
                            else if (header == "Avg Vol (3m):")
                                info.AvgVol3m = cellsData[0].InnerText;
                            else if (header == "Market Cap:")
                                info.MarketCap = cellsData[0].InnerText;
                            else if (header == "P/E (ttm):")
                                info.PE = cellsData[0].InnerText;
                            else if (header == "EPS (ttm):")
                                info.EPS = cellsData[0].InnerText;
                            else if (header == "Div &amp; Yield:")
                                info.Div = cellsData[0].InnerText;
                        }
                    }

                    /*if (isAdd)
                        InfoList.Add(info);*/

                    break;
                }
            }

            return info;
            
        }

    }
}
